package com.javacv.plus.examples.controller;

import com.javacv.plus.extensions.audio.AudioProcessor;
import com.javacv.plus.extensions.audio.AudioResult;
import com.javacv.plus.extensions.audio.config.AudioConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 音频处理控制器
 */
@Slf4j
@RestController
@RequestMapping("/api/audio")
public class AudioController {

    private static final String UPLOAD_DIR = "uploads/audio";
    private static final String OUTPUT_DIR = "output/audio";

    /**
     * 调整音量
     */
    @PostMapping("/volume")
    public ResponseEntity<Map<String, Object>> adjustVolume(
            @RequestParam("file") MultipartFile file,
            @RequestParam("factor") double factor) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("volume");
        
        AudioResult result = AudioProcessor.of(inputPath)
                .volume(factor)
                .save(outputPath);

        return createResponse(result);
    }

    /**
     * 调整速度
     */
    @PostMapping("/speed")
    public ResponseEntity<Map<String, Object>> adjustSpeed(
            @RequestParam("file") MultipartFile file,
            @RequestParam("factor") double factor) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("speed");
        
        AudioResult result = AudioProcessor.of(inputPath)
                .speed(factor)
                .save(outputPath);

        return createResponse(result);
    }

    /**
     * 裁剪音频
     */
    @PostMapping("/trim")
    public ResponseEntity<Map<String, Object>> trimAudio(
            @RequestParam("file") MultipartFile file,
            @RequestParam("startSeconds") double startSeconds,
            @RequestParam("durationSeconds") double durationSeconds) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("trim");
        
        AudioResult result = AudioProcessor.of(inputPath)
                .trim(startSeconds, durationSeconds)
                .save(outputPath);

        return createResponse(result);
    }

    /**
     * 添加淡入效果
     */
    @PostMapping("/fade-in")
    public ResponseEntity<Map<String, Object>> addFadeIn(
            @RequestParam("file") MultipartFile file,
            @RequestParam("durationSeconds") double durationSeconds) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("fade-in");
        
        AudioResult result = AudioProcessor.of(inputPath)
                .fadeIn(durationSeconds)
                .save(outputPath);

        return createResponse(result);
    }

    /**
     * 添加淡出效果
     */
    @PostMapping("/fade-out")
    public ResponseEntity<Map<String, Object>> addFadeOut(
            @RequestParam("file") MultipartFile file,
            @RequestParam("durationSeconds") double durationSeconds) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("fade-out");
        
        AudioResult result = AudioProcessor.of(inputPath)
                .fadeOut(durationSeconds)
                .save(outputPath);

        return createResponse(result);
    }

    /**
     * 添加回声效果
     */
    @PostMapping("/echo")
    public ResponseEntity<Map<String, Object>> addEcho(
            @RequestParam("file") MultipartFile file,
            @RequestParam("delay") double delay,
            @RequestParam("decay") double decay) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("echo");
        
        AudioResult result = AudioProcessor.of(inputPath)
                .echo(delay, decay)
                .save(outputPath);

        return createResponse(result);
    }

    /**
     * 添加混响效果
     */
    @PostMapping("/reverb")
    public ResponseEntity<Map<String, Object>> addReverb(
            @RequestParam("file") MultipartFile file,
            @RequestParam("roomSize") double roomSize,
            @RequestParam("damping") double damping) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("reverb");
        
        AudioResult result = AudioProcessor.of(inputPath)
                .reverb(roomSize, damping)
                .save(outputPath);

        return createResponse(result);
    }

    /**
     * 调整音调
     */
    @PostMapping("/pitch")
    public ResponseEntity<Map<String, Object>> adjustPitch(
            @RequestParam("file") MultipartFile file,
            @RequestParam("factor") double factor) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("pitch");
        
        AudioResult result = AudioProcessor.of(inputPath)
                .pitch(factor)
                .save(outputPath);

        return createResponse(result);
    }

    /**
     * 添加均衡器效果
     */
    @PostMapping("/equalizer")
    public ResponseEntity<Map<String, Object>> addEqualizer(
            @RequestParam("file") MultipartFile file,
            @RequestParam("bands") double[] bands) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("equalizer");
        
        AudioResult result = AudioProcessor.of(inputPath)
                .equalizer(bands)
                .save(outputPath);

        return createResponse(result);
    }

    /**
     * 压缩音频
     */
    @PostMapping("/compress")
    public ResponseEntity<Map<String, Object>> compressAudio(
            @RequestParam("file") MultipartFile file,
            @RequestParam("quality") String quality) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("compress");
        
        AudioResult result = AudioProcessor.of(inputPath)
                .compress(quality)
                .save(outputPath);

        return createResponse(result);
    }

    /**
     * 高级处理（组合多个效果）
     */
    @PostMapping("/advanced")
    public ResponseEntity<Map<String, Object>> advancedProcessing(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "volume", required = false) Double volume,
            @RequestParam(value = "speed", required = false) Double speed,
            @RequestParam(value = "pitch", required = false) Double pitch,
            @RequestParam(value = "echo", required = false) Boolean echo,
            @RequestParam(value = "reverb", required = false) Boolean reverb) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("advanced");
        
        AudioProcessor processor = AudioProcessor.of(inputPath);
        
        if (volume != null) {
            processor.volume(volume);
        }
        if (speed != null) {
            processor.speed(speed);
        }
        if (pitch != null) {
            processor.pitch(pitch);
        }
        if (echo != null && echo) {
            processor.echo(0.5, 0.7);
        }
        if (reverb != null && reverb) {
            processor.reverb(0.8, 0.5);
        }
        
        AudioResult result = processor.save(outputPath);
        return createResponse(result);
    }

    /**
     * 自定义配置处理
     */
    @PostMapping("/custom")
    public ResponseEntity<Map<String, Object>> customProcessing(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "sampleRate", required = false) Integer sampleRate,
            @RequestParam(value = "channels", required = false) Integer channels,
            @RequestParam(value = "bitRate", required = false) Integer bitRate,
            @RequestParam(value = "format", required = false) String format) throws IOException {
        
        String inputPath = saveUploadedFile(file);
        String outputPath = generateOutputPath("custom");
        
        AudioConfig config = new AudioConfig();
        if (sampleRate != null) config.setSampleRate(sampleRate);
        if (channels != null) config.setChannels(channels);
        if (bitRate != null) config.setBitRate(bitRate);
        if (format != null) config.setFormat(format);
        
        AudioResult result = AudioProcessor.of(inputPath, config)
                .save(outputPath);

        return createResponse(result);
    }

    // 辅助方法

    private String saveUploadedFile(MultipartFile file) throws IOException {
        createDirectories();
        String fileName = UUID.randomUUID().toString() + getFileExtension(file.getOriginalFilename());
        Path filePath = Paths.get(UPLOAD_DIR, fileName);
        Files.copy(file.getInputStream(), filePath);
        return filePath.toString();
    }

    private String generateOutputPath(String prefix) {
        try {
            createDirectories();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return Paths.get(OUTPUT_DIR, prefix + "_" + UUID.randomUUID().toString() + ".mp3").toString();
    }

    private void createDirectories() throws IOException {
        Files.createDirectories(Paths.get(UPLOAD_DIR));
        Files.createDirectories(Paths.get(OUTPUT_DIR));
    }

    private String getFileExtension(String fileName) {
        return fileName.substring(fileName.lastIndexOf("."));
    }

    private ResponseEntity<Map<String, Object>> createResponse(AudioResult result) {
        Map<String, Object> response = new HashMap<>();
        response.put("success", result.isSuccess());
        response.put("sourcePath", result.getSourcePath());
        response.put("outputPath", result.getOutputPath());
        response.put("duration", result.getDuration());
        response.put("sampleRate", result.getSampleRate());
        response.put("channels", result.getChannels());
        response.put("bitRate", result.getBitRate());
        response.put("format", result.getFormat());
        
        if (!result.isSuccess()) {
            response.put("error", result.getErrorMessage());
            return ResponseEntity.badRequest().body(response);
        }
        
        return ResponseEntity.ok(response);
    }
} 